﻿using Lib.Data.Enumeration;
using System.Data;
using System.Data.Common;
using System.Data.Odbc;
using System.Text.Json.Serialization;

namespace Lib.Data;
/// <summary>
/// 只能通过 DatabaseFactory 来引用
/// </summary>
[Serializable]
public class DataBase(dbType dbType = dbType.UnClaim) : IDisposable {
    /// <summary>
    /// 创建实例
    /// </summary>
    internal static DataBase Create(dbType dbType = dbType.UnClaim) {
        return new DataBase(dbType);
    }
    [JsonIgnore]
    private DbConnection objConnection = null;
    [JsonIgnore]
    private DbProviderFactory objFactory = null;
    [JsonIgnore]
    private DbCommand objCommand = null;
    /// <summary>
    /// 数据库连接字符串
    /// </summary>
    public string ConnectionString { get; set; }
    /// <summary>
    /// 数据库提供程序名称（已注册的数据库提供程序关键字）
    /// </summary>
    public string ProviderName { get; set; }
    /// <summary>
    /// 连接的数据库类型
    /// </summary>
    public dbType dbType { get; set; } = dbType;
    /// <summary>
    /// 时间戳
    /// </summary>
    public long TimeStamp;
    /// <summary>
    /// 数据库连接关键字名称 或 数据库连接字符串哈希值
    /// </summary>
    public string Key { get; set; }
    /// <summary>
    /// 初始化数据库对象（DbConnection、DbProviderFactory）
    /// </summary>
    public void Init() {
        //
        TimeStamp = DateTime.Now.Ticks;
        //
        if (string.IsNullOrEmpty(ProviderName) || string.IsNullOrEmpty(ConnectionString)) {
            throw new Exception("连接数据库出错,数据库提供程序名称或数据库连接字符串不能为空");
        }
        try {
            objFactory = DbProviderFactories.GetFactory(ProviderName);
        } catch {
            throw new Exception("连接数据库出错,创建数据提供程序引发异常");
        }
        try {
            objConnection = objFactory.CreateConnection();
            objConnection.ConnectionString = ConnectionString;
        } catch {
            objConnection?.Dispose();
            throw new Exception("连接数据库出错,请在配置文件中检查相关配置项");
        } 
    }
    /// <summary>
    /// 数据库连接对象
    /// </summary>
    [JsonIgnore]
    public DbConnection Conn {
        get {
            return objConnection;
        }
    }
    /// <summary>
    /// 
    /// </summary>
    [JsonIgnore]
    public DbProviderFactory Provider {
        get {
            return objFactory;
        }
    }
    /// <summary>
    /// 
    /// </summary>
    [JsonIgnore]
    internal DbCommand CMD {
        get {
            return objCommand;
        }
    }

    #region "事务相关"

    /// <summary>
    /// 事务状态: 0 启动事务, > 0 事务错误次数
    /// </summary>
    internal int Index { get; set; } = -1;
    /// <summary>
    /// 开始事务
    /// </summary>
    public void Begin() {
        Index = 0;
        if (objConnection.State == ConnectionState.Closed) {
            objConnection.Open();
        }
        objCommand = objFactory.CreateCommand();
        objCommand.Connection = objConnection;
        objCommand.Transaction = objConnection.BeginTransaction();
    }
    /// <summary>
    /// 开始事务
    /// </summary>
    public async Task BeginAsync() {
        Index = 0;
        if (objConnection.State == ConnectionState.Closed) {
            await objConnection.OpenAsync();
        }
        objCommand = objFactory.CreateCommand();
        objCommand.Connection = objConnection;
        objCommand.Transaction = await objConnection.BeginTransactionAsync();
    }
    /// <summary>
    /// 递交事务，出错会自动回滚事务
    /// </summary>
    public void Commit() {
        if (Index > -1) {
            try {
                if (Index == 0) {
                    objCommand.Transaction.Commit();
                } else {
                    objCommand.Transaction.Rollback();
                }
            } catch (Exception) {
                objCommand?.Transaction.Rollback();
            } finally {
                objCommand?.Dispose();
            }
        }
        Index = -1;
    }
    /// <summary>
    /// 递交事务，出错会自动回滚事务
    /// </summary>
    public async Task CommitAsync() {
        if (Index > -1) {
            try {
                if (Index == 0) {
                    await objCommand.Transaction.CommitAsync();
                } else {
                    await objCommand.Transaction.RollbackAsync();
                }
            } catch (Exception) {
                await objCommand.Transaction.RollbackAsync();
            } finally {
                objCommand?.Dispose();
            }
        }
        Index = -1;
    }
    /// <summary>
    /// 回滚事务
    /// </summary>
    public void Rollback() {
        if (Index > -1) {
            objCommand.Transaction.Rollback();
        }
        Index = -1;  objCommand?.Dispose();
    }
    /// <summary>
    /// 回滚事务
    /// </summary>
    public async Task RollbackAsync() {
        if (Index > -1) {
            await objCommand.Transaction.RollbackAsync();
        }
        Index = -1; objCommand?.Dispose();
    }

    #endregion

    /// <summary>
    /// 获取参数名的标识字符，默认 "@"
    /// </summary>
    public string ParameterChar { get; set; }
    /// <summary>
    /// 默认执行命令后数据库连接的处理方式
    /// </summary>
    public ConnectionStatus ConnectionStatus { get; set; }
    /// <summary>
    /// 是否开发模式
    /// </summary>
    public bool IsDevelopment { get; set; }
    /// <summary>
    /// 是否启用日志
    /// </summary>
    public bool LogEnable { get; set; }
    /// <summary>
    /// 日志文件关键字
    /// </summary>
    public string LogKey { get; set; }
    /// <summary>
    /// SQL执行时间，超过此设定值[单位毫秒]，才需要记录日志，只有该值等于0会记录所有查询，否则只记录大于该时间的查询
    /// </summary>
    public long? RecordTime { get; set; }
    /// <summary>
    /// 分页模式关键字
    /// </summary>
    public string PagingKey { get; set; }
    /// <summary>
    /// 释放资源
    /// </summary>
    public void Dispose() {
        try {
            objConnection?.Dispose();
            GC.SuppressFinalize(this);
        } catch {

        }
    }
}